﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;

namespace Lon.IO.Ports
{
   public  class ListenerBase<T>:IListener<T>
    {
        Queue<T> dataQueue = new Queue<T>(50001);
        Int32 bufLen = 1000;
        protected IFilter<T> rxFliter = null;

        public IFilter<T> RxFliter
        {
            get { return rxFliter; }
            set { rxFliter = value; }
        }
        

        public Int32 BufLen
        {
            get { return bufLen; }
            set { bufLen = value; }
        }
        AutoResetEvent rxEvent=new AutoResetEvent(false);
        AutoResetEvent rxWaitEvent = new AutoResetEvent(false);
        private void SetEvent()
        {
            rxEvent.Set();
            rxWaitEvent.Set();
        }

        public virtual void Write(T val)
        {
            if(rxFliter!=null)
            {
                if (rxFliter.Comp(val) == false) return;
            }
            lock(dataQueue)
            {
                if (dataQueue.Count >= bufLen)
                {        
                    dataQueue.Dequeue();
                }
                dataQueue.Enqueue(val);
                SetEvent();
            }
           
        }
        public AutoResetEvent RxEvent
        {
            get { return rxWaitEvent; } 
        }
        public virtual bool Read(ref T val,int timeOut)
        {
            try
            {
                if(rxEvent.WaitOne(timeOut,true)==false) return false;
            }
            catch (System.Exception ex)
            {
                return false;
            }
             
            lock(dataQueue)
            {
                if (dataQueue.Count <= 0) return false;
                val = dataQueue.Dequeue();
                if (dataQueue.Count > 0) SetEvent();
                return true;
            }
        }
        public virtual bool Read(ref T val)
        {
            return this.Read(ref val, -1);
        }
        public virtual void ClrBuffer()
        {
            lock(dataQueue)
            {
                dataQueue.Clear();
            }
            rxEvent.Reset();
            rxWaitEvent.Reset();
        }
    }
}
